package edu.usc.cmb.iRegulome.action;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.util.ServletContextAware;

import edu.usc.cmb.iRegulome.action.util.ScpDownload;
import edu.usc.cmb.iRegulome.action.util.ScpFile;
import edu.usc.cmb.iRegulome.action.util.SshConnection;
import edu.usc.cmb.iregulome.dao.SampleStudyDAO;
import edu.usc.cmb.iregulome.entity.ChipSeqBroadPeaksEntity;
import edu.usc.cmb.iregulome.entity.ChipSeqPeaksEntity;

public class FileGenAction extends ActionWithSampleStudyDAO implements
		ServletContextAware, ServletRequestAware {

	private final Logger log = LogManager.getLogger(FileGenAction.class);

	private ServletContext cxt;

	private HttpServletRequest request;

	private String sampleId;

	private List<ChipSeqPeaksEntity> chipSeqPeaksEntityList;

	private InputStream peakBedInputStream;

	private InputStream densityBigBedInputStream;

	private String trackLine;

	private long contentLength;

	private String forGraph = "false";

	public FileGenAction(SampleStudyDAO sampleStudyDAO) {
		super(sampleStudyDAO);
	}

	public void setSampleId(String sampleId) {
		this.sampleId = sampleId;
	}

	public String getSampleId() {
		return sampleId;
	}

	public void setChipSeqPeaksEntityList(
			List<ChipSeqPeaksEntity> chipSeqPeaksEntityList) {
		this.chipSeqPeaksEntityList = chipSeqPeaksEntityList;
	}

	public List<ChipSeqPeaksEntity> getChipSeqPeaksEntityList() {
		return chipSeqPeaksEntityList;
	}

	public String getPeakBEDFile() {

		log.debug("Generate the peak bed file for " + sampleId);
		File BEDfile = new File(this.cxt.getRealPath("./BED/" + sampleId
				+ "Peak.bed"));

		// if bed file doesn't exist
		if (!BEDfile.exists()) {
			log.debug("Peak bed file doesn't exist for " + sampleId);
			List<ChipSeqPeaksEntity> chipSeqEntity = getSampleStudyDAO()
					.retrieveChipSeqBySampleId(sampleId);

			List<ChipSeqBroadPeaksEntity> chipSeqBroadPeaksEntity = getSampleStudyDAO()
					.retrieveChipSeqBPeaksBySampleId(sampleId);

			try {
				BufferedWriter bw = new BufferedWriter(new FileWriter(BEDfile));
				bw.write("track type=bedGraph name=\"" + sampleId
						+ " Peaks\" description=\"" + sampleId
						+ " Peaks\" visibility=full \n");
				for (ChipSeqPeaksEntity chipSeq : chipSeqEntity) {
					String seqLine = chipSeq.getId().getChrom() + "\t"
							+ chipSeq.getId().getChromStart() + "\t"
							+ chipSeq.getChromEnd() + "\t-\t"
							+ chipSeq.getScore() + "\n";
					bw.write(seqLine);
					bw.flush();
				}

				bw.write("track type=bedGraph name=\"" + sampleId
						+ " BroadPeaks\" description=\"" + sampleId
						+ " BroadPeaks\" visibility=full \n");
				for (ChipSeqBroadPeaksEntity chipSeq : chipSeqBroadPeaksEntity) {
					String seqLine = chipSeq.getId().getChrom() + "\t"
							+ chipSeq.getId().getChromStart() + "\t"
							+ chipSeq.getChromEnd() + "\t-\t"
							+ chipSeq.getScore() + "\n";
					bw.write(seqLine);
					bw.flush();
				}

				if (forGraph.equals("true")) {
					
					
					generateDensityBigBEDFile();

					bw.write("track type=bigWig name=\""
							+ sampleId
							+ " Wig Format\" description=\""
							+ sampleId
							+ " smoothed background tag density\" visibility=full color=200,100,0 altColor=0,100,200 priority=20"
							+ " bigDataUrl=http://dl403m-1.cmb.usc.edu:8180/iRegulome/BED/"
							+ sampleId + "Density.bw");
					bw.flush();

				}

				bw.close();

			} catch (IOException e) {
				log.error("Generate peak bed file for " + sampleId, e);
			}
		}

		try {
			setContentLength(BEDfile.length());
			setPeakBedInputStream(new FileInputStream(BEDfile));
		} catch (FileNotFoundException e) {
			log.error("Can not find the file " + BEDfile);
		}

		return "SUCCESS";

	}

	private void generateDensityBigBEDFile() {

		log.debug("Generate the density wig file for " + sampleId);

		File bigBEDFile = new File(this.cxt.getRealPath("./BED/" + sampleId
				+ "Density.bw"));

		if (!bigBEDFile.exists()) {

			File BEDfile = new File(this.cxt.getRealPath("./BED/" + sampleId
					+ "Density.bed"));

			try {
				ScpFile scpFile = new ScpFile(BEDfile,
						"/home/cmbpanfs-01/siyuanh/iRegulome/ChIP-seq/"
								+ sampleId + "/cexample.density.wig");
				ScpDownload sd = new ScpDownload(scpFile);
				SshConnection sc = new SshConnection("hpc-cmb.usc.edu",
						"siyuanh", "FENBeKU28nKh");
				sc.connect();
				sc.executeTask(sd);
				sc.disconnect();

				String scriptPath = this.cxt.getRealPath("./WEB-INF/script/");
				String bedCmd = scriptPath
						+ "/wigToBigWig "
						+ BEDfile.getAbsolutePath()
						+ " "
						+ scriptPath
						+ "/hg18.chrom.sizes "
						+ this.cxt.getRealPath("./BED/" + sampleId
								+ "Density.bw");
				Process p = Runtime.getRuntime().exec(bedCmd);
				p.waitFor();
				p.destroy();

				BEDfile.delete();
			} catch (Exception e1) {
				log.error("Generate the density wig file for sample "
						+ sampleId, e1);
			}
		}

	}

	/**
	 * Struts action to get the density file in big wig format
	 * @return
	 */
	public String getDensityBigBEDFile() {

		generateDensityBigBEDFile();

		try {
			setContentLength(new File(this.cxt.getRealPath("./BED/" + sampleId
					+ "Density.bw")).length());
			setDensityBigBedInputStream(new FileInputStream(this.cxt
					.getRealPath("./BED/" + sampleId + "Density.bw")));
		} catch (FileNotFoundException e) {
			log.error("Density wig file for sample " + sampleId
					+ " doesn't exist", e);
		}

		return "SUCCESS";

	}

	public String genBigBEDTrackFile() {

		log
				.debug("Customize the density wig file track for sample "
						+ sampleId);

		generateDensityBigBEDFile();

		request
				.setAttribute(
						"trackLine",
						"track type=bigWig name=\""
								+ sampleId
								+ " Wig Format\" description=\""
								+ sampleId
								+ " smoothed background tag density\" visibility=full color=200,100,0 altColor=0,100,200 priority=20"
								+ " bigDataUrl=http://dl403m-1.cmb.usc.edu:8180/iRegulome/BED/"
								+ sampleId + "Density.bw");

		return "SUCCESS";
	}

	@Override
	public void setServletContext(ServletContext context) {
		this.cxt = context;
	}

	public void setPeakBedInputStream(InputStream peakBedInputStream) {
		this.peakBedInputStream = peakBedInputStream;
	}

	public InputStream getPeakBedInputStream() {
		return peakBedInputStream;
	}

	public void setDensityBigBedInputStream(InputStream densityBigBedInputStream) {
		this.densityBigBedInputStream = densityBigBedInputStream;
	}

	public InputStream getDensityBigBedInputStream() {
		return densityBigBedInputStream;
	}

	public void setTrackLine(String trackLine) {
		this.trackLine = trackLine;
	}

	public String getTrackLine() {
		return trackLine;
	}

	public void setContentLength(long contentLength) {
		this.contentLength = contentLength;
	}

	public long getContentLength() {
		return contentLength;
	}

	@Override
	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}
	
	
	public void setForGraph(String forGraph) {
		this.forGraph = forGraph;
	}
	
	public String getForGraph() {
		return forGraph;
	}

}
